<template>
	<div>HelloWord</div>
	<h3>{{ a }}</h3>
	<button @click="butRef">Ref++</button>
	<h3>{{ b.age }}</h3>
	<button @click="butReactive">butReactive++</button>
	<h4 @click="newCD">
		ref对象:{{ c }} <br />
		reactive对象:{{ d }}
	</h4>
</template>

<script>
import { defineComponent } from "vue";
export default defineComponent({
	name: "HelloWord",
});
</script>

<script setup>
/* setup执行的时机
在beforeCreate之前执行(一次), 此时组件对象还没有创建
this是undefined,
不能通过this来访问data/computed/methods / props
其实所有的composition API相关回调函数中也都不可以
*/
import { ref, reactive } from "vue";
// 当前的写法为vue3语法糖，setup写在script标签内部
console.log("语法糖setup");

// 使用ref定义：
// 注意：ref定义的数据在js中要使用.value才能读取
// 在没模板中直接使用{{变量}}使用
const a = ref(1);
console.log(a.value);

// 验证响应式ref
const butRef = () => {
	console.log(a.value);
	a.value++;
};

// 使用reactive
const obj = {
	name: "xiaoming",
	age: 18,
};
/*
    reactive对象
      在使用该方法的过程中,一共存在两个对象,一个成为代理对象,一个成为源数据对象(元对象)
      使用reactive函数,可以返回一个代理对象

      开发者对代理对象做的任何事情,元对象也会受到相同的效果
      如果操作代理对象内部的某个子对象,也具有响应式效果
      注意:操作代理对象可以实现响应式效果,但是操作元对象是没有响应式效果的,所以开发中不要操作元对象

  */
/*
 作用: 定义多个数据的响应式
const proxy = reactive(obj): 接收一个普通对象然后返回该普通对象的响应式代理器对象
响应式转换是“深层的”：会影响对象内部所有嵌套的属性
内部基于 ES6 的 Proxy 实现，通过代理对象操作源对象内部数据都是响应式的
*/

const b = reactive(obj);
console.log(b);

// 验证响应式reactive对象
const butReactive = () => {
	b.age++;
	console.log("响应式对象", b, "元对象", obj);
};

/*
    面试题:ref和reactive的区别
      相同点:
        ref和reactive都可以将一个对象变成具有响应式的效果

      不同点:
        ref如果接收到一个全新的对象,该对象也能实现响应式的特点
        reactive会返回一个代理对象,存入某个变量中,但是如果对该变量进行重新赋值,很可能会失去响应式的特点
  */

//  不同点验证：
let c = ref({
	name: "小c",
	age: 18,
});
let d = reactive({
	name: "小d",
	age: 18,
});

// 给c,d赋予新对象
const newCD = () => {
	c.value = {
		name: "新小c",
		age: 19,
	};
	// 将会丢弃响应式对象
	d = {
		name: "新小d",
		age: 20,
	};
};
</script>
